/*************************************************
Author: byron
Date: 12/27/2012
Description:
Notes: 
*************************************************/

#ifndef __CRankArray_h__
#define __CRankArray_h__

#include "CTArray.h"

template<typename T, int COUNT>
class CRankArray : public CTArray<T,COUNT>
{
public:
    CRankArray()
    {
    }

    virtual ~CRankArray()
    {
    }

    virtual bool IsSame(T&, T&) const
    {
        return false;
    }

    // a > b, 返回大于0,　　a < b, 返回小于0
    virtual int CmpFunc(T & a, T & b) const
    {
        return 0;
    }

    int GetRank (T & tValue)
    {
        for (int i = 0; i < CTArray<T,COUNT>::m_iUsedCount; ++i)
        {
            if (IsSame(tValue, CTArray<T,COUNT>::m_astData[i]))
            {
                return i;
            }
        }

        return -1;
    }

    //第一名传入1
    int GetRankByOder (int iOrder, T & tValue)
    {
        if (iOrder > CTArray<T,COUNT>::m_iUsedCount || iOrder <= 0)
        {
            return -1;
        }

        tValue = CTArray<T,COUNT>::m_astData[iOrder - 1];

        return 0;
    }

	/*
	更新以CTArray为基础的排名榜 支持数值正负变化
    声明一个CRankArray实例时候需要在cpp文件中实现IsSame和CmpFunc
    iOld 表示更新前的排名 iNew 表示更新后的排名 都从0开始 -1表示不在榜中
	返回值：0
	*/
    int Update(T& t, int& iOld, int& iNew)
    {
        //支持数值正负变化后的更新

        bool bAdd = true;
        bool bSwap = false;

        iOld = -1;
        iNew = -1;

        T stSwap = t;
        T stTemp = t;

        for (int i = 0; i < CTArray<T,COUNT>::Size(); ++i)
        {
            if ((!bSwap && CmpFunc(stSwap, CTArray<T,COUNT>::m_astData[i]) > 0) ||
                (bSwap && CmpFunc(stSwap, CTArray<T,COUNT>::m_astData[i]) >= 0))
            {
                if (bSwap)
                {
                    if (IsSame(t, CTArray<T,COUNT>::m_astData[i]))//单元已在榜中但排名变前
                    {
                        bAdd = false;
                        iOld = i;
                        CTArray<T,COUNT>::m_astData[i] = stSwap;
                        break;
                    }
                    else
                    {
                        stTemp = CTArray<T,COUNT>::m_astData[i];
                        CTArray<T,COUNT>::m_astData[i] = stSwap;
                        stSwap = stTemp;
                    }
                }
                else
                {
                    if (IsSame(t, CTArray<T,COUNT>::m_astData[i]))//单元已在榜中但排名没变
                    {
                        bAdd = false;
                        iOld = i;
                        iNew = i;
                        CTArray<T,COUNT>::m_astData[i] = stSwap;
                        break;
                    }
                    else
                    {
                        bSwap = true;
                        iNew = i;
                        stTemp = CTArray<T,COUNT>::m_astData[i];
                        CTArray<T,COUNT>::m_astData[i] = stSwap;
                        stSwap = stTemp;
                    }
                }
            }
            else if (IsSame(t, CTArray<T,COUNT>::m_astData[i]))//单元已在榜中但排名变后
            {
                bAdd = false;
                iOld = i;
                CTArray<T,COUNT>::m_astData[i] = stSwap;

                for ( ; i + 1 < CTArray<T,COUNT>::Size(); ++i)
                {
                    if (CmpFunc(CTArray<T,COUNT>::m_astData[i], CTArray<T,COUNT>::m_astData[i+1]) < 0)
                    {
                        stTemp = CTArray<T,COUNT>::m_astData[i];
                        CTArray<T,COUNT>::m_astData[i] = CTArray<T,COUNT>::m_astData[i+1];
                        CTArray<T,COUNT>::m_astData[i+1] = stTemp;
                        iNew = i + 1;
                    }
                    else
                    {
                        break;
                    }
                }
    
                break;
            }
        }
    
        if (bAdd && CTArray<T,COUNT>::Size() < CTArray<T,COUNT>::GetCount())
        {
            if (iNew >= 0)
            {
                CTArray<T,COUNT>::AddOneItem(stSwap);
            }
            else
            {
                iNew = CTArray<T,COUNT>::AddOneItem(stSwap);
            }
        }
    
        return 0;
    }

    int Update(T& t)
    {
        int iTmp = 0;
        return Update(t, iTmp, iTmp);
    }

};

#endif // __CRankArray_h__

